const fs = require('fs-extra')
const path = require('path')
const JSON5 = require('json5')
const Mock = require('mockjs2')
const { delay } = require('./utils.js')

// 接口前缀
const devServerMockUrlMatch = /^\/api\//

async function getMockData(dataFilePath, method) {
	const fileJsonPath = `${dataFilePath}.json`
	const fileMockjsPath = `${dataFilePath}.mockjs.json`
	const fileRestFulPath = `${dataFilePath}$${method.toLowerCase()}.json`
	const fileRestFulMockjsPath = `${dataFilePath}$${method.toLowerCase()}.mockjs.json`
	const fileExist = await fs.pathExists(dataFilePath)
	const fileJsonExist = await fs.pathExists(fileJsonPath)
	const fileMockjsExist = await fs.pathExists(fileMockjsPath)
	const fileRestFulExist = await fs.pathExists(fileRestFulPath)
	const fileRestFulMockjsExist = await fs.pathExists(fileRestFulMockjsPath)

	// 先寻找 RESTFul .mockjs.json 文件
	if (fileRestFulMockjsExist) {
		return fs.readFile(fileRestFulMockjsPath, 'utf8').then(json => JSON.stringify(Mock.mock(JSON5.parse(json))))
	}

	// 再寻找 RESTFul .json 数据文件
	if (fileRestFulExist) {
		return fs.readFile(fileRestFulPath, 'utf8')
	}

	// 再寻找 .mockjs.json 后缀 mock 数据文件
	if (fileMockjsExist) {
		return fs.readFile(fileMockjsPath, 'utf8').then(json => JSON.stringify(Mock.mock(JSON5.parse(json))))
	}

	// 再寻找 .json 后缀 mock 数据文件
	if (fileJsonExist) {
		return fs.readFile(fileJsonPath, 'utf8')
	}

	// 再寻找无后缀 mock 数据文件
	if (fileExist) {
		return fs.readFile(dataFilePath, 'utf8')
	}

	console.error('------- ERROR ------')
	console.error('尝试了以下可能的 mock 数据文件，仍没有找到对应的数据')
	console.error(`1. ${fileRestFulPath}`)
	console.error(`2. ${fileRestFulMockjsPath}`)
	console.error(`3. ${fileJsonPath}`)
	console.error(`4. ${fileMockjsExist}`)
	console.error(`5. ${dataFilePath}`)
	return Promise.reject(new Error('没有找到对应mock数据文件'))
}

module.exports = app => {
	// 只有环境变量是mock的情况才会进入
	if (process.env.NODE_ENV === 'mock') {
		console.info('开启本地mock数据调试模式...')
		app.all(devServerMockUrlMatch, async (req, res) => {
			const { method, originalUrl } = req
			console.info(`本地数据请求：[${method}] ${originalUrl}`)
			try {
				// 响应延迟500ms，模拟请求
				await delay(500)
				const dataFilePath = originalUrl
					.replace(devServerMockUrlMatch, `${path.join(process.cwd(), 'mock/testdata')}$&`)
					.replace(/\?.*$/, '')
				let data = await getMockData(dataFilePath, method)

				res.append('Access-Control-Allow-Origin', true)
				try {
					data = JSON5.parse(data)
				} catch (e) {
					const errMsg = `local mock json data parse error (本地测试数据JSON解析错误): ${dataFilePath}`
					throw new Error(`${errMsg}\n${e}`)
				}
				res.json(data)
			} catch (err) {
				console.error(err)
				res.status(500).send(err.stack)
			}
		})
	}
}
